home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Examples / Split-Screen Scrolling / Sprite Stuff.c < prev    next >
Encoding:
Text File  |  2000-10-06  |  20.8 KB  |  663 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Sprite Stuff.c
  3. ///--------------------------------------------------------------------------------------
  4.  
  5. #include <SWIncludes.h>
  6. #include <SWGameUtils.h>
  7. #include "SWApplication.h"
  8.  
  9. #include "Split-Screen Demo.h"
  10. #include "Sprite Stuff.h"
  11.  
  12.  
  13.     // Pointers to the original sprites which we clone
  14.     // when we want to add a sprite to the animation.
  15.     // We never add these sprites themselves to the animation.
  16.     
  17. SpritePtr    gMasterTank1SpriteP,
  18.             gMasterTank2SpriteP,
  19.             gMasterBulletSpriteP,
  20.             gMasterGunPowerUpSpriteP;
  21.             
  22.  
  23. extern WindowPtr            gWindowP;
  24. extern SpriteWorldPtr        gMasterSpriteWorldP, gCloneSpriteWorldP;
  25. extern SpriteLayerPtr        gTankSpriteLayerP, gBulletSpriteLayerP, gPowerUpSpriteLayerP;
  26. extern TileMapStructPtr        gTileMapStructP;
  27. extern TileMapPtr            gTileMap;
  28. extern Rect                    gMasterRect, gCloneRect;
  29. extern Rect                    gMoveBoundsRect;
  30. extern DrawProcPtr            gSpriteMaskDrawProc;
  31. extern RgnHandle            gTempRgn;                    // Used by TankHitDrawProc
  32.  
  33. extern KeyStruct             gTank1Keys, gTank2Keys;
  34.  
  35.  
  36. ///--------------------------------------------------------------------------------------
  37. // LoadSprites
  38. ///--------------------------------------------------------------------------------------
  39.  
  40. void    LoadSprites( void )
  41. {
  42.     OSErr            err;
  43.     
  44.         // Load gMasterTank1SpriteP
  45.     err = SWCreateSpriteFromSinglePictXY(gMasterSpriteWorldP, &gMasterTank1SpriteP,
  46.             NULL, 128, 128, 50, 50, 0, 0, 18, kFatMask);
  47.     SetUpSprite(gMasterTank1SpriteP, err);
  48.     
  49.         // Load gMasterTank2SpriteP
  50.     err = SWCreateSpriteFromSinglePictXY(gMasterSpriteWorldP, &gMasterTank2SpriteP,
  51.             NULL, 129, 129, 50, 50, 0, 0, 18, kFatMask);
  52.     SetUpSprite(gMasterTank2SpriteP, err);
  53.     
  54.         // Load gMasterBulletSpriteP
  55.     err = SWCreateSpriteFromCicnResource(gMasterSpriteWorldP, &gMasterBulletSpriteP, 
  56.             NULL, 128, 1, kFatMask);
  57.     SetUpSprite(gMasterBulletSpriteP, err);
  58.     SWSetFrameHotSpot(gMasterBulletSpriteP->curFrameP, kHalfBulletSize, kHalfBulletSize);
  59.     
  60.         // Load gMasterGunPowerUpSpriteP
  61.     err = SWCreateSpriteFromCicnResource(gMasterSpriteWorldP, &gMasterGunPowerUpSpriteP, 
  62.             NULL, 130, 1, kFatMask);
  63.     SetUpSprite(gMasterGunPowerUpSpriteP, err);
  64. }
  65.  
  66.  
  67. ///--------------------------------------------------------------------------------------
  68. // DisposeSprites - we must dispose of each sprite we loaded, since they are not
  69. // added to the SpriteWorld, and therefore will not be disposed with the SpriteWorld.
  70. ///--------------------------------------------------------------------------------------
  71.  
  72. void    DisposeSprites( void )
  73. {
  74.     SWDisposeSprite(&gMasterTank1SpriteP);
  75.     SWDisposeSprite(&gMasterTank2SpriteP);
  76.     SWDisposeSprite(&gMasterBulletSpriteP);
  77. }
  78.  
  79.  
  80. ///--------------------------------------------------------------------------------------
  81. // SetUpSprite - makes the LoadSprites code a little cleaner.
  82. ///--------------------------------------------------------------------------------------
  83.  
  84. void    SetUpSprite(SpritePtr mySpriteP, OSErr err)
  85. {
  86.     FatalError(err);
  87.     
  88.     if (gMasterSpriteWorldP->pixelDepth >= 8)
  89.         SWCompileSprite(mySpriteP);
  90.     
  91.     SWSetSpriteMoveBounds(mySpriteP, &gMasterSpriteWorldP->scrollRectMoveBounds);
  92.     SWSetSpriteDrawProc(mySpriteP, gSpriteMaskDrawProc);
  93.     SWLockSprite(mySpriteP);
  94. }
  95.  
  96.  
  97. ///--------------------------------------------------------------------------------------
  98. // NewTankSprite - clone the master sprite and add the clone to the animation.
  99. // Also allocate memory for the custom sprite structure.
  100. ///--------------------------------------------------------------------------------------
  101.  
  102. SpritePtr    NewTankSprite( short tankType )
  103. {
  104.     TankStructPtr    tankStructP;
  105.     SpritePtr        tankSpriteP;
  106.     OSErr            err;
  107.     
  108.         // Allocate memory for the TankStruct
  109.     tankStructP = (TankStructPtr)NewPtr(sizeof(TankStruct));
  110.     FatalError( MemError() );
  111.     
  112.     if (tankType == kPlayer1)
  113.         err = SWCloneSprite(gMasterTank1SpriteP, &tankSpriteP, tankStructP);
  114.     else
  115.         err = SWCloneSprite(gMasterTank2SpriteP, &tankSpriteP, tankStructP);
  116.     FatalError(err);
  117.     
  118.     SWAddSprite(gTankSpriteLayerP, tankSpriteP);
  119.     SWSetSpriteMoveProc(tankSpriteP, TankSpriteMoveProc);
  120.     
  121.     if (tankType == kPlayer1)
  122.         SWSetCurrentFrameIndex(tankSpriteP, kTankRightFrameIndex);
  123.     else
  124.         SWSetCurrentFrameIndex(tankSpriteP, kTankLeftFrameIndex);
  125.     
  126.     tankStructP->tankType = tankType;
  127.     tankStructP->numBulletsOnScreen = 0;
  128.     tankStructP->nextShotDelay = 0;
  129.     tankStructP->gunType = kNormalGun;
  130.     tankStructP->damage = 0;
  131.     tankStructP->canShoot = true;
  132.     tankStructP->wasHit = false;
  133.     SW_SET_RECT(tankStructP->insetRect, 10, 10, 10, 10);
  134.     
  135.     return tankSpriteP;
  136. }
  137.  
  138.  
  139. ///--------------------------------------------------------------------------------------
  140. // NewBulletSprite - clone the master sprite and add the clone to the animation.
  141. // Also allocate memory for the custom sprite structure.
  142. ///--------------------------------------------------------------------------------------
  143.  
  144. SpritePtr    NewBulletSprite( void )
  145. {
  146.     BulletStructPtr    bulletStructP;
  147.     SpritePtr        bulletSpriteP;
  148.     OSErr            err;
  149.     
  150.         // Allocate memory for the BulletStruct
  151.     bulletStructP = (BulletStructPtr)NewPtr(sizeof(BulletStruct));
  152.     FatalError( MemError() );
  153.  
  154.     err = SWCloneSprite(gMasterBulletSpriteP, &bulletSpriteP, bulletStructP);
  155.     FatalError(err);
  156.     
  157.     SWAddSprite(gBulletSpriteLayerP, bulletSpriteP);
  158.     SWSetSpriteMoveProc(bulletSpriteP, BulletSpriteMoveProc);
  159.     SWSetSpriteCollideProc(bulletSpriteP, BulletSpriteCollideProc);
  160.     
  161.     bulletStructP->numMovesLeft = 30;
  162.  
  163.     return bulletSpriteP;
  164. }
  165.  
  166.  
  167. ///--------------------------------------------------------------------------------------
  168. // NewPowerUpSprite - clone the master sprite and add the clone to the animation.
  169. ///--------------------------------------------------------------------------------------
  170.  
  171. SpritePtr    NewPowerUpSprite( GunType gunType )
  172. {
  173.     SpritePtr        powerUpSpriteP;
  174.     OSErr            err;
  175.  
  176.     err = SWCloneSprite(gMasterGunPowerUpSpriteP, &powerUpSpriteP, NULL);
  177.     FatalError(err);
  178.     
  179.     SWAddSprite(gPowerUpSpriteLayerP, powerUpSpriteP);
  180.     SWSetSpriteCollideProc(powerUpSpriteP, PowerUpCollideProc);
  181.     
  182.     powerUpSpriteP->userData = gunType;
  183.  
  184.     return powerUpSpriteP;
  185. }
  186.  
  187.  
  188. ///--------------------------------------------------------------------------------------
  189. // TankSpriteMoveProc
  190. ///--------------------------------------------------------------------------------------
  191.  
  192. SW_FUNC void TankSpriteMoveProc(SpritePtr tankSpriteP)
  193. {
  194.     TankStructPtr        tankStructP = (TankStructPtr)tankSpriteP;
  195.     TankDirectionType    currentDirection;
  196.     KeyStruct            *tankKeysP;
  197.     
  198.         // Determine whether to use keys for player 1 or player 2
  199.     if (tankStructP->tankType == kPlayer1)
  200.         tankKeysP = &gTank1Keys;
  201.     else
  202.         tankKeysP = &gTank2Keys;
  203.     
  204.     
  205.         // If the tank was just hit and flashed white, change back to normal drawProc
  206.     if (tankStructP->wasHit)
  207.     {
  208.         tankStructP->wasHit = false;
  209.         tankSpriteP->needsToBeDrawn = true;
  210.         SWSetSpriteDrawProc(tankSpriteP, gSpriteMaskDrawProc);
  211.     }
  212.     
  213.     
  214.         // Figure out which direction we're going
  215.     if (tankKeysP->up)
  216.     {
  217.         if (tankKeysP->right)
  218.             currentDirection = kTankUpRightFrameIndex;
  219.         else if (tankKeysP->left)
  220.             currentDirection = kTankUpLeftFrameIndex;
  221.         else
  222.             currentDirection = kTankUpFrameIndex;
  223.     }
  224.     else if (tankKeysP->down)
  225.     {
  226.         if (tankKeysP->right)
  227.             currentDirection = kTankDownRightFrameIndex;
  228.         else if (tankKeysP->left)
  229.             currentDirection = kTankDownLeftFrameIndex;
  230.         else
  231.             currentDirection = kTankDownFrameIndex;
  232.     }
  233.     else
  234.     {
  235.         if (tankKeysP->right)
  236.             currentDirection = kTankRightFrameIndex;
  237.         else if (tankKeysP->left)
  238.             currentDirection = kTankLeftFrameIndex;
  239.         else 
  240.             currentDirection = kNoDirection;
  241.     }
  242.     
  243.     
  244.         // Set the current frame index, and store current direction
  245.     if (currentDirection != kNoDirection)
  246.     {
  247.         SWSetCurrentFrameIndex(tankSpriteP, currentDirection);
  248.     }
  249.     
  250.     
  251.         // Move the tank
  252.     switch (currentDirection)
  253.     {
  254.         case kTankUpFrameIndex:
  255.             tankSpriteP->horizMoveDelta = 0;
  256.             tankSpriteP->vertMoveDelta = -kTankSpeed;
  257.             break;
  258.         case kTankUpRightFrameIndex:
  259.             tankSpriteP->horizMoveDelta = kTankSpeed/1.5;
  260.             tankSpriteP->vertMoveDelta = -kTankSpeed/1.5;
  261.             break;
  262.         case kTankRightFrameIndex:
  263.             tankSpriteP->horizMoveDelta = kTankSpeed;
  264.             tankSpriteP->vertMoveDelta = 0;
  265.             break;
  266.         case kTankDownRightFrameIndex:
  267.             tankSpriteP->horizMoveDelta = kTankSpeed/1.5;
  268.             tankSpriteP->vertMoveDelta = kTankSpeed/1.5;
  269.             break;
  270.         case kTankDownFrameIndex:
  271.             tankSpriteP->horizMoveDelta = 0;
  272.             tankSpriteP->vertMoveDelta = kTankSpeed;
  273.             break;
  274.         case kTankDownLeftFrameIndex:
  275.             tankSpriteP->horizMoveDelta = -kTankSpeed/1.5;
  276.             tankSpriteP->vertMoveDelta = kTankSpeed/1.5;
  277.             break;
  278.         case kTankLeftFrameIndex:
  279.             tankSpriteP->horizMoveDelta = -kTankSpeed;
  280.             tankSpriteP->vertMoveDelta = 0;
  281.             break;
  282.         case kTankUpLeftFrameIndex:
  283.             tankSpriteP->horizMoveDelta = -kTankSpeed/1.5;
  284.             tankSpriteP->vertMoveDelta = -kTankSpeed/1.5;
  285.             break;
  286.         default:
  287.             tankSpriteP->horizMoveDelta = 0;
  288.             tankSpriteP->vertMoveDelta = 0;
  289.             break;
  290.     }
  291.     
  292.     
  293.             // Slow the tank down if it is in contact with mud
  294.     if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWEntireSprite,
  295.             &tankStructP->insetRect, 0, 0, kMudTile, kMudTile, false) )
  296.     {
  297.         tankSpriteP->horizMoveDelta /= 2;
  298.         tankSpriteP->vertMoveDelta /= 2;
  299.     }
  300.     
  301.     
  302.     tankSpriteP->destFrameRect.top += tankSpriteP->vertMoveDelta;
  303.     tankSpriteP->destFrameRect.bottom += tankSpriteP->vertMoveDelta;
  304.  
  305.  
  306.         // Check for collisions with walls vertically
  307.     if (tankSpriteP->vertMoveDelta > 0)            // Moving down
  308.     {
  309.         if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWBottomSide, 
  310.             &tankStructP->insetRect, 0, 0, kFirstWallTile, kLastWallTile, true) )
  311.         {
  312.             tankSpriteP->vertMoveDelta = 0;
  313.         }
  314.     }
  315.     else if (tankSpriteP->vertMoveDelta < 0)        // Moving up
  316.     {
  317.         if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWTopSide,  
  318.             &tankStructP->insetRect, 0, 0, kFirstWallTile, kLastWallTile, true) )
  319.         {
  320.             tankSpriteP->vertMoveDelta = 0;
  321.         }
  322.     }
  323.     
  324.  
  325.     tankSpriteP->destFrameRect.right += tankSpriteP->horizMoveDelta;
  326.     tankSpriteP->destFrameRect.left += tankSpriteP->horizMoveDelta;
  327.     
  328.             // Check for collisions with walls horizontally
  329.     if (tankSpriteP->horizMoveDelta > 0)            // Moving right
  330.     {
  331.         if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWRightSide,  
  332.             &tankStructP->insetRect, 0, 0, kFirstWallTile, kLastWallTile, true) )
  333.         {
  334.             tankSpriteP->horizMoveDelta = 0;
  335.         }
  336.     }
  337.     else if (tankSpriteP->horizMoveDelta < 0)        // Moving left
  338.     {
  339.         if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWLeftSide,
  340.             &tankStructP->insetRect, 0, 0, kFirstWallTile, kLastWallTile, true) )
  341.         {
  342.             tankSpriteP->horizMoveDelta = 0;
  343.         }
  344.     }
  345.     
  346.             // Damage the tank if it hits lava
  347.     if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWEntireSprite,
  348.             &tankStructP->insetRect, 0, 0, kFirstLavaTile, kFirstLavaTile, false) )
  349.     {
  350.         DamageTank(tankSpriteP, 4);
  351.     }
  352.     
  353.     
  354.     tankSpriteP->needsToBeDrawn = true;
  355.     
  356.     
  357.     if (tankKeysP->shoot)
  358.     {
  359.         if (tankStructP->canShoot)
  360.         {
  361.             tankStructP->canShoot = false;
  362.         
  363.             if ( (tankStructP->numBulletsOnScreen < kMaxNumBullets) || tankStructP->gunType == kMachineGun)
  364.                 ShootBullet(tankSpriteP);
  365.         }
  366.         else if (tankStructP->gunType == kMachineGun)
  367.         {
  368.             tankStructP->nextShotDelay++;
  369.             if (tankStructP->nextShotDelay >= kNextShotDelay)
  370.             {
  371.                 tankStructP->nextShotDelay = 0;
  372.                 tankStructP->canShoot = true;
  373.             }
  374.         }
  375.     }
  376.     else if (tankStructP->gunType == kMachineGun && tankStructP->canShoot == false)
  377.     {
  378.         tankStructP->nextShotDelay++;
  379.         if (tankStructP->nextShotDelay >= kNextShotDelay)
  380.         {
  381.             tankStructP->nextShotDelay = 0;
  382.             tankStructP->canShoot = true;
  383.         }
  384.     }
  385.     else
  386.     {
  387.         tankStructP->canShoot = true;
  388.     }    
  389. }
  390.  
  391.  
  392. ///--------------------------------------------------------------------------------------
  393. //  BulletSpriteMoveProc
  394. ///--------------------------------------------------------------------------------------
  395.  
  396. SW_FUNC void BulletSpriteMoveProc(SpritePtr bulletSpriteP)
  397. {
  398.     BulletStructPtr    bulletStructP = (BulletStructPtr)bulletSpriteP;
  399.     short    tileRow, tileCol, tileID;
  400.     
  401.     tileID = SWReturnTileUnderPixel(gMasterSpriteWorldP, 0,
  402.         bulletSpriteP->destFrameRect.left + kHalfBulletSize,
  403.         bulletSpriteP->destFrameRect.top + kHalfBulletSize);
  404.     
  405.     if ( tileID >= kFirstWallTile && tileID <= kLastWallTile )
  406.     {
  407.             // Remove the bullet - it hit a wall
  408.         bulletStructP->parentStructP->numBulletsOnScreen--;
  409.         SWRemoveSpriteFromAnimation(gMasterSpriteWorldP, bulletSpriteP, true);
  410.     
  411.             // Convert pixel coordinates to tileMap coordinates
  412.         tileRow = (bulletSpriteP->destFrameRect.top + kHalfBulletSize) / kTileHeight;
  413.         tileCol = (bulletSpriteP->destFrameRect.left + kHalfBulletSize) / kTileWidth;
  414.         
  415.             // Damage the wall
  416.         tileID += kWallDamageOffset;
  417.         if (tileID > kLastWallTile)
  418.             tileID = kMainFloorTile;
  419.         
  420.             // Change the tile in *both* SpriteWorlds.
  421.         SWDrawTile(gMasterSpriteWorldP, 0, tileRow, tileCol, tileID);
  422.         SWDrawTile(gCloneSpriteWorldP, 0, tileRow, tileCol, tileID);
  423.     }
  424.     else if (bulletStructP->numMovesLeft-- <= 0)
  425.     {
  426.             // Remove the bullet - it has moved past its range
  427.         bulletStructP->parentStructP->numBulletsOnScreen--;
  428.         SWRemoveSpriteFromAnimation(gMasterSpriteWorldP, bulletSpriteP, true);
  429.     }
  430.     
  431.     SWOffsetSprite(bulletSpriteP, bulletSpriteP->horizMoveDelta, bulletSpriteP->vertMoveDelta);
  432. }
  433.  
  434.  
  435. ///--------------------------------------------------------------------------------------
  436. //  DeadTankFrameProc
  437. ///--------------------------------------------------------------------------------------
  438.  
  439. SW_FUNC void DeadTankFrameProc(SpritePtr tankSpriteP, FramePtr curFrameP, long *frameIndex)
  440. {
  441.     #pragma         unused(curFrameP)    // Let CodeWarrior know this variable is unused
  442.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  443.     
  444.     if (*frameIndex < kLastTankBlowUpFrame)
  445.         *frameIndex += 1;
  446.     else
  447.     {
  448.             // Make the tank as good as new
  449.         SWSetCurrentFrameIndex(tankSpriteP, kTankRightFrameIndex);
  450.         tankStructP->gunType = kNormalGun;
  451.         tankStructP->damage = 0;
  452.         tankStructP->wasHit = false;
  453.         SWSetSpriteDrawProc(tankSpriteP, gSpriteMaskDrawProc);
  454.         SWSetSpriteFrameProc(tankSpriteP, NULL);
  455.         SWSetSpriteFrameTime(tankSpriteP, -1);
  456.         SWSetSpriteMoveProc(tankSpriteP, TankSpriteMoveProc);
  457.         
  458.         if (tankStructP->tankType == kPlayer1)
  459.             SWMoveSprite(tankSpriteP, gMoveBoundsRect.left + 120, gMoveBoundsRect.top + 100);
  460.         else 
  461.             SWMoveSprite(tankSpriteP, gMoveBoundsRect.right-140, gMoveBoundsRect.bottom-140);
  462.     }
  463. }
  464.  
  465.  
  466. ///--------------------------------------------------------------------------------------
  467. // ShootBullet
  468. ///--------------------------------------------------------------------------------------
  469.  
  470. void    ShootBullet(SpritePtr tankSpriteP)
  471. {
  472.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  473.     SpritePtr        newBulletSpriteP;
  474.         
  475.     newBulletSpriteP = NewBulletSprite();
  476.     ((BulletStructPtr)newBulletSpriteP)->parentStructP = tankStructP;
  477.     tankStructP->numBulletsOnScreen++;
  478.     
  479.     SWSetSpriteLocation(newBulletSpriteP, 
  480.             tankSpriteP->destFrameRect.left + kHalfTankWidth,
  481.             tankSpriteP->destFrameRect.top + kHalfTankHeight);
  482.     
  483.     switch (tankSpriteP->curFrameIndex)
  484.     {
  485.         case kTankUpFrameIndex:
  486.             SWSetSpriteMoveDelta(newBulletSpriteP, 0, -kBulletSpeed);
  487.             SWOffsetSprite(newBulletSpriteP, 0, -kHalfTankHeight-5);
  488.             break;
  489.         case kTankUpRightFrameIndex:
  490.             SWSetSpriteMoveDelta(newBulletSpriteP, kBulletSpeed, -kBulletSpeed);
  491.             SWOffsetSprite(newBulletSpriteP, kHalfTankWidth+5, -kHalfTankHeight-5);
  492.             break;
  493.         case kTankRightFrameIndex:
  494.             SWSetSpriteMoveDelta(newBulletSpriteP, kBulletSpeed, 0);
  495.             SWOffsetSprite(newBulletSpriteP, kHalfTankWidth+5, 0);
  496.             break;
  497.         case kTankDownRightFrameIndex:
  498.             SWSetSpriteMoveDelta(newBulletSpriteP, kBulletSpeed, kBulletSpeed);
  499.             SWOffsetSprite(newBulletSpriteP, kHalfTankWidth+5, kHalfTankHeight+5);
  500.             break;
  501.         case kTankDownFrameIndex:
  502.             SWSetSpriteMoveDelta(newBulletSpriteP, 0, kBulletSpeed);
  503.             SWOffsetSprite(newBulletSpriteP, 0, kHalfTankHeight+5);
  504.             break;
  505.         case kTankDownLeftFrameIndex:
  506.             SWSetSpriteMoveDelta(newBulletSpriteP, -kBulletSpeed, kBulletSpeed);
  507.             SWOffsetSprite(newBulletSpriteP, -kHalfTankWidth-5, kHalfTankHeight+5);
  508.             break;
  509.         case kTankLeftFrameIndex:
  510.             SWSetSpriteMoveDelta(newBulletSpriteP, -kBulletSpeed, 0);
  511.             SWOffsetSprite(newBulletSpriteP, -kHalfTankWidth-5, 0);
  512.             break;
  513.         case kTankUpLeftFrameIndex:
  514.             SWSetSpriteMoveDelta(newBulletSpriteP, -kBulletSpeed, -kBulletSpeed);
  515.             SWOffsetSprite(newBulletSpriteP, -kHalfTankWidth-5, -kHalfTankHeight-5);
  516.             break;
  517.         default:
  518.             break;
  519.     }
  520. }
  521.  
  522.  
  523. ///--------------------------------------------------------------------------------------
  524. //   BulletSpriteCollideProc
  525. ///--------------------------------------------------------------------------------------
  526.  
  527. SW_FUNC void BulletSpriteCollideProc(
  528.     SpritePtr    bulletSpriteP,
  529.     SpritePtr    tankSpriteP,
  530.     Rect*        sectRect)
  531. {
  532.     #pragma            unused(sectRect)    // Let CodeWarrior know this variable is unused
  533.     Boolean            hasCollided;
  534.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  535.     
  536.         // Exit if the tank is in the process of being blown up
  537.     if (tankStructP->damage > kMaximumDamage)
  538.         return;
  539.     
  540.         // See if the actual sprite images collided
  541.     if (gMasterSpriteWorldP->pixelDepth >= 8)
  542.         hasCollided = SWPixelCollision(bulletSpriteP, tankSpriteP);    // Faster, but 8-bits & above only
  543.     else
  544.         hasCollided = SWRegionCollision(bulletSpriteP, tankSpriteP); // Works in any depth
  545.  
  546.     if (hasCollided)
  547.     {
  548.             // Remove the bullet
  549.         ((BulletStructPtr)bulletSpriteP)->parentStructP->numBulletsOnScreen--;
  550.         SWRemoveSpriteFromAnimation(gMasterSpriteWorldP, bulletSpriteP, true);
  551.         
  552.         DamageTank(tankSpriteP, 10);
  553.     }
  554. }
  555.  
  556.  
  557. ///--------------------------------------------------------------------------------------
  558. //   PowerUpCollideProc
  559. ///--------------------------------------------------------------------------------------
  560.  
  561. SW_FUNC void PowerUpCollideProc(
  562.     SpritePtr    powerUpSpriteP,
  563.     SpritePtr    tankSpriteP,
  564.     Rect*        sectRect)
  565. {
  566.     #pragma            unused(sectRect)    // Let CodeWarrior know this variable is unused
  567.     Boolean            hasCollided;
  568.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  569.     
  570.  
  571.         // See if the actual sprite images collided
  572.     if (gMasterSpriteWorldP->pixelDepth >= 8)
  573.         hasCollided = SWPixelCollision(powerUpSpriteP, tankSpriteP); // Faster, but 8-bits & above only
  574.     else
  575.         hasCollided = SWRegionCollision(powerUpSpriteP, tankSpriteP); // Works in any depth
  576.  
  577.     if (hasCollided)
  578.     {
  579.             // Pick it up only if we don't already have it
  580.         if (tankStructP->gunType != powerUpSpriteP->userData)
  581.         {
  582.             tankStructP->gunType = powerUpSpriteP->userData;
  583.             
  584.                 // Remove the power-up Sprite
  585.             SWRemoveSpriteFromAnimation(gMasterSpriteWorldP, powerUpSpriteP, true);
  586.         }
  587.     }
  588. }
  589.  
  590.  
  591. ///--------------------------------------------------------------------------------------
  592. //   DamageTank
  593. ///--------------------------------------------------------------------------------------
  594.  
  595. void    DamageTank( SpritePtr tankSpriteP, short damageAmount )
  596. {
  597.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  598.     
  599.         // Increase the tank's damage
  600.     tankStructP->damage += damageAmount;
  601.     if (tankStructP->damage > kMaximumDamage)
  602.     {
  603.             // Kill the tank
  604.         SWSetSpriteMoveProc(tankSpriteP, NULL);    // A dead tank can't move.
  605.         SWSetSpriteFrameProc(tankSpriteP, DeadTankFrameProc); // Blow it up!
  606.         SWSetSpriteFrameTime(tankSpriteP, 1000/10);    // Show animation at 10fps
  607. //        SWSetCurrentFrameIndex(tankSpriteP, kFirstTankBlowUpFrame-1);
  608.     }
  609.     else
  610.     {
  611.             // Make the tank flash yellow
  612.         tankStructP->wasHit = true;
  613.         tankSpriteP->needsToBeDrawn = true;
  614.         SWSetSpriteDrawProc(tankSpriteP, TankHitDrawProc);
  615.     }
  616. }
  617.  
  618.  
  619.  
  620. ///--------------------------------------------------------------------------------------
  621. //    TankHitDrawProc - Note: this DrawProc requires the sprite to have a maskRgn. If you
  622. //    look at NewSprite(), you'll see that the tank sprite was loaded with kFatMask, 
  623. //    instead of kPixelMask, so this drawProc could be used.
  624. //
  625. //    Note also that since PaintRgn gives us no option to clip our drawing to the dstRect,
  626. //    we turn the dstRect into a region and "clip" the frame's region to the dstRect
  627. //    region with SectRgn. An alternative would be to call ClipRect to set the current
  628. //    clipping region to dstRect before making the call to PaintRgn. (Remembering to 
  629. //    restore the old clipping region when done). This clipping must be done because
  630. //    sometimes (especially in scrolling games) only part of a sprite needs to be drawn,
  631. //    and drawing outside the dstRect could cause problems.
  632. ///--------------------------------------------------------------------------------------
  633.  
  634. SW_FUNC void TankHitDrawProc(
  635.     FramePtr srcFrameP,
  636.     FramePtr dstFrameP,
  637.     Rect* srcRect,
  638.     Rect* dstRect)
  639. {
  640.     #pragma unused(dstFrameP)    // Let CodeWarrior know this variable is unused
  641.     
  642.     if (srcFrameP->maskRgn != NULL)
  643.     {
  644.         Rect rgnRect = (**srcFrameP->maskRgn).rgnBBox;
  645.  
  646.             // move the mask region to the sprite location
  647.         OffsetRgn(srcFrameP->maskRgn,
  648.             (dstRect->left - (srcRect->left - srcFrameP->frameRect.left) - rgnRect.left) 
  649.             + srcFrameP->offsetPoint.h,
  650.             (dstRect->top - (srcRect->top - srcFrameP->frameRect.top) - rgnRect.top)
  651.             + srcFrameP->offsetPoint.v);
  652.         
  653.             // Here we "clip" the srcFrameP->maskRgn with the dstRect.
  654.         RectRgn(gTempRgn, dstRect);
  655.         SectRgn(gTempRgn, srcFrameP->maskRgn, gTempRgn);
  656.         
  657.         ForeColor(yellowColor);
  658.         PaintRgn(gTempRgn);
  659.         ForeColor(blackColor);
  660.     }
  661. }
  662.  
  663.